﻿#include "FITKAbaqusAdaptorPredefinedField.h"
#include "InpKeyLineSpliter.h"
#include "FITKAbaqusINPReader.h"
#include "FITKAbaqusINPWriter.h"
#include "FITK_Kernel/FITKCore/FITKEnumTransformer.hpp"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaPredefinedFieldTemperature.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaPredefinedFieldVelocity.h"
#include "FITK_Component/FITKAbaqusData/FITKDataCase.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaAmplitudeManager.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaPredefinedFieldManager.h"
#include "FITK_Interface/FITKInterfaceStructural/FITKAbaStepManager.h"
#include "FITK_Interface/FITKInterfaceModel/FITKAbstractModelComponent.h"
#include "FITK_Interface/FITKInterfaceModel/FITKAbstractModel.h"

namespace IO
{
    QString FITKAbaqusAdaptorPredefinedField::getAdaptorClass()
    {
        //返回数据类名 带命名空间
        return "IO::FITKAbaqusAdaptorPredefinedField";
    }

    void FITKAbaqusAdaptorPredefinedField::setCaseData(AbaqusData::FITKDataCase* caseData)
    {
        //设置算例数据
        _caseData = caseData;
        _tool.setCaseData(_caseData);
    }

    void FITKAbaqusAdaptorPredefinedField::setLineKeywords(QString line)
    {
        //设置行数据
        _keywordsLine = line;
    }

    bool FITKAbaqusAdaptorPredefinedField::isValueEmpty()
    {
        return _isValueEmp;
    }

    void FITKAbaqusAdaptorPredefinedField::setPredefinedFieldDeactiveStepR(QString word, int stepId)
    {
        if (!_caseData)return;
        //获取预定义管理器
        Interface::FITKAbaPredefinedFieldManager* predefinedFieldManager = _caseData->getPredefinedFieldManager();
        if (!predefinedFieldManager)return;
        int count = predefinedFieldManager->getDataCount();
        //类型
        QList <Interface::FITKAbaAbstractPredefinedField::FITKAbaPredefinedFiledType> typeList;
        if (word.toLower() == "temperature")
            typeList << Interface::FITKAbaAbstractPredefinedField::FITKAbaPredefinedFiledType::Temperature;
        if (typeList.isEmpty())return;
        //获取类型一致的预定义场在当前step中取消激活
        for (int i = 0; i < count; ++i)
        {
            Interface::FITKAbaAbstractPredefinedField* fieldData = dynamic_cast<Interface::FITKAbaAbstractPredefinedField*>(predefinedFieldManager->getDataByIndex(i));
            if (!fieldData || !typeList.contains(fieldData->getPreDefinedType()))continue;
            if (fieldData->getCreatedStep() == stepId || fieldData->getStateInStep(stepId) == Interface::FITKAbaStepEnum::StateInStep::ResetToInitial || fieldData->getStateInStep(stepId) == Interface::FITKAbaStepEnum::StateInStep::None) continue;
            if (fieldData->getPreDefinedType() == Interface::FITKAbaAbstractPredefinedField::FITKAbaPredefinedFiledType::Temperature)
            {
                Interface::FITKAbaPredefinedFieldTemperature* field = dynamic_cast<Interface::FITKAbaPredefinedFieldTemperature*>(fieldData);
                if (!field)continue;
                field->setStateInStep(Interface::FITKAbaStepEnum::StateInStep::ResetToInitial, stepId);
            }
            
        }
    }

    void FITKAbaqusAdaptorPredefinedField::setWriterData(QString op, int stepId)
    {
        _op = op;
        _stepId = stepId;
    }

    bool FITKAbaqusAdaptorPredefinedField::adaptR()
    {
        //读取
        Interface::FITKAbaAbstractPredefinedField* fieldData = dynamic_cast<Interface::FITKAbaAbstractPredefinedField*>(_dataObj);
        if (!fieldData || !_reader || !_caseData)return false;
        bool readOK = false;
        //获取类型
        Interface::FITKAbaAbstractPredefinedField::FITKAbaPredefinedFiledType fieldType = fieldData->getPreDefinedType();
        if (fieldType == Interface::FITKAbaAbstractPredefinedField::FITKAbaPredefinedFiledType::Temperature)
            readOK = this->readPredefinedFiledTemperature();
        else if (fieldType == Interface::FITKAbaAbstractPredefinedField::FITKAbaPredefinedFiledType::Velocity)
            readOK = this->readPredefinedFiledVelocity();
        return true;
    }

    bool FITKAbaqusAdaptorPredefinedField::adaptW()
    {
        //写出
        Interface::FITKAbaAbstractPredefinedField* fieldData = dynamic_cast<Interface::FITKAbaAbstractPredefinedField*>(_dataObj);
        if (!fieldData || !_writer || !_caseData)return false;
        bool writerOK = false;
        //获取类型
        Interface::FITKAbaAbstractPredefinedField::FITKAbaPredefinedFiledType fieldType = fieldData->getPreDefinedType();
        if (fieldType == Interface::FITKAbaAbstractPredefinedField::FITKAbaPredefinedFiledType::Temperature)
            writerOK = this->writePredefinedFiledTemperature();
        else if (fieldType == Interface::FITKAbaAbstractPredefinedField::FITKAbaPredefinedFiledType::Velocity)
            writerOK = this->writePredefinedFiledVelocity();

        return writerOK;
    }

    bool FITKAbaqusAdaptorPredefinedField::readPredefinedFiledTemperature()
    {
        //温度预定义场
        Interface::FITKAbaPredefinedFieldTemperature* fieldData = dynamic_cast<Interface::FITKAbaPredefinedFieldTemperature*>(_dataObj);
        if (!fieldData || !_reader || !_caseData)return false;
        //获取预定义管理器
        Interface::FITKAbaPredefinedFieldManager* predefinedFieldManager = _caseData->getPredefinedFieldManager();
        if (!predefinedFieldManager)return false;
        //获取幅值管理器
        Interface::FITKAbaAmplitudeManager* amplitudeManager = _caseData->getAmplitudeManager();
        if (!amplitudeManager)return false;
        //处理关键字数据
        InpKeyLineSpliter s(_keywordsLine, _reader);
        bool ok = false;
        if (s.hasKey("amplitude"))
        {
            auto amplitudeData = amplitudeManager->getDataByName(s["amplitude"]);
            if (!amplitudeData)return false;
            fieldData->setAmplitudeId(amplitudeData->getDataObjectID());
        }
        //读取数据
        _reader->backLine();
        QString line = _reader->readLine();
        QStringList str = line.split(',');
        if (str.size() < 2)return false;
        //获取集合和模型
        int instanceId = -1;
        int setID = _tool.getSetIDByName(str.at(0).trimmed(), -1, instanceId);
        if (setID == -1)return false;
        fieldData->setComponent(setID);
        fieldData->setModel(instanceId);
        //获取数据
        double value = str.at(1).trimmed().toDouble(&ok);
        if (!ok)return false;
        if (str.size() == 2)
        {
            fieldData->setMagnitude(value);
        }

        //机制处理
        int stepId = fieldData->getCreatedStep();
        int count = predefinedFieldManager->getDataCount();
        for (int i = 0; i < count; ++i)
        {
            Interface::FITKAbaPredefinedFieldTemperature* data = dynamic_cast<Interface::FITKAbaPredefinedFieldTemperature*>(predefinedFieldManager->getDataByIndex(i));
            if (!data || fieldData->getStateInStep(stepId) == Interface::FITKAbaStepEnum::StateInStep::ResetToInitial || fieldData->getStateInStep(stepId) == Interface::FITKAbaStepEnum::StateInStep::None || data->getPreDefinedType() != fieldData->getPreDefinedType())continue;
            if (data->getCreatedStep() == stepId || setID != data->getComponentID())continue;
            data->setStateInStep(Interface::FITKAbaStepEnum::StateInStep::ResetToInitial, stepId);
        }
        return true;
    }

    bool FITKAbaqusAdaptorPredefinedField::readPredefinedFiledVelocity()
    {
        Interface::FITKAbaPredefinedFieldVelocity* fieldData = dynamic_cast<Interface::FITKAbaPredefinedFieldVelocity*>(_dataObj);
        if (!fieldData || !_reader || !_caseData)return false;
        //获取预定义管理器
        Interface::FITKAbaPredefinedFieldManager* predefinedFieldManager = _caseData->getPredefinedFieldManager();
        if (!predefinedFieldManager)return false;
        //读取数据
        _reader->backLine();
        QString line = _reader->readLine().trimmed();
        QStringList str = line.split(',');
        bool ok = false;
        if (str.size() < 3)return false;
        //获取集合和模型
        int instanceId = -1;
        int setID = _tool.getSetIDByName(str.at(0).trimmed(), -1, instanceId);
        if (setID == -1)return false;
        fieldData->setComponent(setID);
        fieldData->setModel(instanceId);
        if (str.size() == 3)
        {
            fieldData->setDefinition(Interface::FITKAbaPredefinedFieldVelocity::VelocityDefinition::TranslationalOnly);
            int num = str.at(1).trimmed().toInt(&ok);
            if (!ok)return false;
            double value = str.at(2).trimmed().toDouble(&ok);
            if (!ok)return false;
            if (num < 1 || num > 3)return false;
            if (num == 1)
                fieldData->setV1(value);
            else if (num == 2)
                fieldData->setV2(value);
            else if (num == 3)
                fieldData->setV3(value);
            //记录数据是否为空
            if (fabsl(value) < 1e-15)
                _isValueEmp = true;
            return true;
        }
        if (str.size() < 5)return false;
        //angular Velocity
        double angularVelocityValue = str.at(1).trimmed().toDouble(&ok);
        if (!ok)return false;
        if (str.at(2).trimmed().isEmpty() && str.at(3).trimmed().isEmpty() && str.at(4).trimmed().isEmpty())
            fieldData->setDefinition(Interface::FITKAbaPredefinedFieldVelocity::VelocityDefinition::RotationalOnly);
        else
            fieldData->setDefinition(Interface::FITKAbaPredefinedFieldVelocity::VelocityDefinition::TranslationalAndRotational);
        //V1
        double v1Value = 0.0;
        if (!str.at(2).trimmed().isEmpty())
        {
            v1Value = str.at(2).trimmed().toDouble(&ok);
            if (!ok)return false;
        }
        //V2
        double v2Value = 0.0;
        if (!str.at(3).trimmed().isEmpty())
        {
            v2Value = str.at(3).trimmed().toDouble(&ok);
            if (!ok)return false;
        }
        //V3
        double v3Value = 0.0;
        if (!str.at(4).trimmed().isEmpty())
        {
            v3Value = str.at(4).trimmed().toDouble(&ok);
            if (!ok)return false;
        }
        //设置数据
        fieldData->setAngularVelocity(angularVelocityValue);
        fieldData->setV1(v1Value);
        fieldData->setV2(v2Value);
        fieldData->setV3(v3Value);
        //获取两点坐标
        line = _reader->readLine().trimmed();
        str = line.split(',');
        if (str.size() < 6)return false;
        std::array<double, 3> point1{ 0.0 , 0.0, 0.0 };
        std::array<double, 3> point2{ 0.0 , 0.0, 0.0 };
        point1[0] = str.at(0).trimmed().toDouble(&ok);
        if (!ok)return false;
        point1[1] = str.at(1).trimmed().toDouble(&ok);
        if (!ok)return false;
        point1[2] = str.at(2).trimmed().toDouble(&ok);
        if (!ok)return false;
        point2[0] = str.at(3).trimmed().toDouble(&ok);
        if (!ok)return false;
        point2[1] = str.at(4).trimmed().toDouble(&ok);
        if (!ok)return false;
        point2[2] = str.at(5).trimmed().toDouble(&ok);
        if (!ok)return false;
        //设置两点数据
        fieldData->setAxisPoint1(point1);
        fieldData->setAxisPoint2(point2);

        //机制处理
        //int stepId = fieldData->getCreatedStep();
        //int count = predefinedFieldManager->getDataCount();
        //for (int i = 0; i < count; ++i)
        //{
        //    Interface::FITKAbaPredefinedFieldVelocity* data = dynamic_cast<Interface::FITKAbaPredefinedFieldVelocity*>(predefinedFieldManager->getDataByIndex(i));
        //    if (!data || fieldData->getActiveState() == Interface::FITKAbaStepEnum::StateInStep::ResetToInitial || fieldData->getActiveState() == Interface::FITKAbaStepEnum::StateInStep::None || data->getPreDefinedType() != fieldData->getPreDefinedType())continue;
        //    if (data->getCreatedStep() == stepId || setID != data->getComponentID())continue;
        //    data->setDeactiveStep(stepId);
        //}
        return true;
    }

    bool FITKAbaqusAdaptorPredefinedField::writePredefinedFiledTemperature()
    {
        //温度预定义场
        Interface::FITKAbaPredefinedFieldTemperature* fieldData = dynamic_cast<Interface::FITKAbaPredefinedFieldTemperature*>(_dataObj);
        if (!fieldData || !_writer || !_caseData)return false;
        QTextStream* stream = _writer->getStream();
        *stream << QString("** Name: %1  Type: %2").arg(fieldData->getDataObjectName()).arg("Temperature") << endl;
        //step, amplitude管理器
        Interface::FITKAbaAmplitudeManager* amplitudeManager = _caseData->getAmplitudeManager();
        Interface::FITKAbaStepManager* stepManager = _caseData->getStepManager();
        if (!amplitudeManager || !stepManager)return false;
        //记录op
        QString lineOne;
        if (!_op.isEmpty())
            lineOne += _op;
        //输出取消激活
        if (_stepId == -1)
        {
            *stream << QString("*Temperature%1").arg(lineOne) << endl;
            return true;
        }
        //写出amplitude
        auto ampData = amplitudeManager->getDataByID(fieldData->getAmplitudeId(_stepId));
        if (ampData)
        {
            QString ampName = ampData->getDataObjectName();
            ampName = ampName.contains(' ') ? QString("\"%1\"").arg(ampName) : ampName;
            lineOne += QString(", amplitude=%1").arg(ampName);
        }
        //用于判断是否是initStep
        auto initStep = stepManager->getDataByIndex(0);
        if (!initStep)return false;
        if (initStep->getDataObjectID() == _stepId)
            *stream << QString("*Initial Conditions, type=TEMPERATURE%1").arg(lineOne) << endl;
        else
            *stream << QString("*Temperature%1").arg(lineOne) << endl;
        //获取set
        auto set = fieldData->getComponentObj();
        if (!set)return false;
        QString setName = set->getDataObjectName();
        setName = setName.contains(' ') ? QString("\"%1\"").arg(setName) : setName;
        if (fieldData->getModelObj() && fieldData->getModelID() != set->getAbsModelID() && fieldData->getModelObj()->getAbsModelType() == Interface::FITKModelEnum::AbsModelType::AssInstance)
        {
            QString name = fieldData->getModelObj()->getDataObjectName();
            name = name.contains(' ') ? QString("\"%1\"").arg(name) : name;
            setName = name + "." + setName;
        }
        *stream << setName << QString(", %1").arg(_writer->double2String(fieldData->getMagnitude(), 8, 0)) << endl;
        return true;
    }

    bool FITKAbaqusAdaptorPredefinedField::writePredefinedFiledVelocity()
    {
        //速度预定义场
        Interface::FITKAbaPredefinedFieldVelocity* fieldData = dynamic_cast<Interface::FITKAbaPredefinedFieldVelocity*>(_dataObj);
        if (!fieldData || !_writer || !_caseData)return false;
        QTextStream* stream = _writer->getStream();
        *stream << QString("** Name: %1  Type: %2").arg(fieldData->getDataObjectName()).arg("Velocity") << endl;
        //step, amplitude管理器
        Interface::FITKAbaAmplitudeManager* amplitudeManager = _caseData->getAmplitudeManager();
        Interface::FITKAbaStepManager* stepManager = _caseData->getStepManager();
        if (!amplitudeManager || !stepManager)return false;
        if (fieldData->getDefinition() == Interface::FITKAbaPredefinedFieldVelocity::VelocityDefinition::TranslationalOnly)
            *stream << QString("*Initial Conditions, type=VELOCITY") << endl;
        else
            *stream << QString("*Initial Conditions, type=ROTATING VELOCITY") << endl;
        //获取set
        auto set = fieldData->getComponentObj();
        if (!set)return false;
        QString setName = set->getDataObjectName();
        setName = setName.contains(' ') ? QString("\"%1\"").arg(setName) : setName;
        if (fieldData->getModelObj() && fieldData->getModelID() != set->getAbsModelID() && fieldData->getModelObj()->getAbsModelType() == Interface::FITKModelEnum::AbsModelType::AssInstance)
        {
            QString name = fieldData->getModelObj()->getDataObjectName();
            name = name.contains(' ') ? QString("\"%1\"").arg(name) : name;
            setName = name + "." + setName;
        }
        if (fieldData->getDefinition() == Interface::FITKAbaPredefinedFieldVelocity::VelocityDefinition::TranslationalOnly)
        {
            if (fabsl(fieldData->getV1()) > 1e-15)
                *stream << QString("%1, 1, %2").arg(setName).arg(_writer->double2String(fieldData->getV1(), 8, 0)) << endl;
            if (fabsl(fieldData->getV2()) > 1e-15)
                *stream << QString("%1, 2, %2").arg(setName).arg(_writer->double2String(fieldData->getV2(), 8, 0)) << endl;
            if (fabsl(fieldData->getV3()) > 1e-15)
                *stream << QString("%1, 3, %2").arg(setName).arg(_writer->double2String(fieldData->getV3(), 8, 0)) << endl;
        }
        else if (fieldData->getDefinition() == Interface::FITKAbaPredefinedFieldVelocity::VelocityDefinition::RotationalOnly)
        {
            std::array<double, 3> point1 = fieldData->getAxisPoint1();
            std::array<double, 3> point2 = fieldData->getAxisPoint2();
            *stream << QString("%1, %2,  ,  ,  , ").arg(setName).arg(_writer->double2String(fieldData->getAngularVelocity(), 8, 0)) << endl;
            *stream << QString("%1, %2, %3, %4, %5, %6, ").arg(_writer->double2String(point1[0], 8, 0)).arg(_writer->double2String(point1[1], 8, 0)).arg(_writer->double2String(point1[2], 8, 0))
                .arg(_writer->double2String(point2[0], 8, 0)).arg(_writer->double2String(point2[1], 8, 0)).arg(_writer->double2String(point2[2], 8, 0)) << endl;
        }
        else if (fieldData->getDefinition() == Interface::FITKAbaPredefinedFieldVelocity::VelocityDefinition::TranslationalAndRotational)
        {
            std::array<double, 3> point1 = fieldData->getAxisPoint1();
            std::array<double, 3> point2 = fieldData->getAxisPoint2();
            *stream << QString("%1, %2, %3, %4, %5, ").arg(setName).arg(_writer->double2String(fieldData->getAngularVelocity(), 8, 0))
                .arg(_writer->double2String(fieldData->getV1(), 8, 0)).arg(_writer->double2String(fieldData->getV2(), 8, 0)).arg(_writer->double2String(fieldData->getV3(), 8, 0)) << endl;
            *stream << QString("%1, %2, %3, %4, %5, %6, ").arg(_writer->double2String(point1[0], 8, 0)).arg(_writer->double2String(point1[1], 8, 0)).arg(_writer->double2String(point1[2], 8, 0))
                .arg(_writer->double2String(point2[0], 8, 0)).arg(_writer->double2String(point2[1], 8, 0)).arg(_writer->double2String(point2[2], 8, 0)) << endl;
        }
        return true;
    }
}
